import React, { PureComponent } from 'react';
import { Icon, Checkbox, Dropdown, Input } from 'antd';

import styles from './index.less';

const { Search } = Input;

class DropdownCheckList extends PureComponent {
  static getDerivedStateFromProps(props, state) {
    const { dataSource = [], selectedValues = [], valueKey = 'value' } = props;
    const { oldDatasource = [], oldSelectedValues = [] } = state;
    const newState = {};
    if (dataSource || selectedValues) {
      const newSource = dataSource
        .map(item => item[valueKey])
        .sort()
        .join('');
      const oldSource = oldDatasource
        .map(item => item[valueKey])
        .sort()
        .join('');
      const newValues = selectedValues.sort().join('');
      const oldValues = oldSelectedValues.sort().join('');
      if (newSource !== oldSource) {
        newState.oldDatasource = [...dataSource];
        newState.dataSource = [...dataSource];
      }
      if (newValues !== oldValues) {
        newState.oldSelectedValues = [...selectedValues];
        newState.selectedValues = [...selectedValues];
      }
      if (newState.dataSource || newState.selectedValues) {
        newState.indeterminate = dataSource.length > selectedValues.length;
        newState.checkedAll = selectedValues.length === dataSource.length;
      }
    }
    return Object.keys.length > 0 ? newState : null;
  }

  state = {
    dataSource: [],
    selectedValues: [],
    indeterminate: true,
    checkedAll: false
  };

  componentDidMount() {
    const mask = document.createElement('div');
    mask.className = 'dropdown-mask';
    this.setState({ mask });
  }

  visibleChange = visible => {
    const { mask, selectedValues, oldSelectedValues } = this.state;
    if (!visible) {
      // mask.removeEventListener('click', this.hideDropdown, false);
      mask.remove();
      const { onCheckChange } = this.props;
      const wasChange = selectedValues.sort().join('') !== oldSelectedValues.sort().join('');
      if (onCheckChange && wasChange) onCheckChange(selectedValues);
    } else {
      // mask.addEventListener('click', this.hideDropdown, false);
      document.body.appendChild(mask);
    }
    const { onOpenChange } = this.props;
    if (onOpenChange) onOpenChange(!visible);
  };

  showMask = visible => {
    const { mask } = this.state;
    if (visible) {
      // document.documentElement.style.overflow = 'hidden';
      mask.addEventListener('click', this.hideDropdown, false);
      document.body.appendChild(mask);
    } else {
      // document.documentElement.style.overflow = '';
      mask.removeEventListener('click', this.hideDropdown, false);
      mask.remove();
    }
  };

  hideDropdown = () => {
    const { selectedValues = [], oldSelectedValues = [] } = this.state;
    const wasChange = selectedValues.sort().join('') !== oldSelectedValues.sort().join('');
    this.setState({ open: false, oldSelectedValues: selectedValues });
    this.showMask(false);
    const { onCheckChange } = this.props;
    if (onCheckChange && wasChange) onCheckChange(selectedValues);
    const { onOpenChange } = this.props;
    if (onOpenChange) onOpenChange(false);
  };

  openDropdown = () => {
    this.setState({ open: true });
    this.showMask(true);
    const { onOpenChange } = this.props;
    if (onOpenChange) onOpenChange(true);
  };

  checkGroupChange = checkedList => {
    const { dataSource } = this.state;
    const { valueKey, maxSelectNum } = this.props;
    const newSource = dataSource.map(item => {
      const it = item;
      it.disabled = checkedList.length >= maxSelectNum && checkedList.indexOf(item[valueKey]) < 0;
      return it;
    });
    this.setState({
      selectedValues: checkedList,
      dataSource: newSource,
      indeterminate: !!checkedList.length && checkedList.length < maxSelectNum,
      checkedAll: checkedList.length >= maxSelectNum
    });
  };

  checkChange = e => {
    const { dataSource, selectedValues = [] } = this.state;
    const { valueKey, maxSelectNum = dataSource.length } = this.props;
    const { checked, value } = e.target;
    const index = selectedValues.indexOf(value);
    let checkedList = selectedValues;
    if (checked && index < 0) {
      checkedList = [...checkedList, value];
    }
    if (!checked && index > -1) {
      checkedList.splice(index, 1);
    }
    const newSource = dataSource.map(item => {
      const it = item;
      it.disabled = checkedList.length >= maxSelectNum && checkedList.indexOf(item[valueKey]) < 0;
      return it;
    });
    this.setState({
      selectedValues: checkedList,
      dataSource: newSource,
      indeterminate: !!checkedList.length && checkedList.length < maxSelectNum,
      checkedAll: checkedList.length >= maxSelectNum
    });
  };

  checkAllChange = e => {
    const { dataSource } = this.state;
    const { valueKey, maxSelectNum = dataSource.length } = this.props;
    let selecteds = e.target.checked ? dataSource.filter(it => !it.filter).map(item => item[valueKey]) : [];
    if (selecteds.length >= maxSelectNum) {
      selecteds = selecteds.slice(0, maxSelectNum);
    }
    const newSource = dataSource.map(item => {
      const it = item;
      it.disabled = selecteds.length >= maxSelectNum && selecteds.indexOf(item[valueKey]) < 0;
      return it;
    });
    this.setState({
      selectedValues: selecteds,
      dataSource: newSource,
      indeterminate: !!selecteds.length && selecteds.length < maxSelectNum,
      checkedAll: selecteds.length >= maxSelectNum
    });
  };

  search = value => {
    const val = value.toLocaleLowerCase();
    const { dataSource } = this.state;
    const { textKey, valueKey } = this.props;
    const events = dataSource.map(item => {
      const it = item;
      it.filter = item[textKey].toLocaleLowerCase().indexOf(val) < 0 && item[valueKey].toLocaleLowerCase().indexOf(val) < 0;
      return it;
    });
    this.setState({ dataSource: events });
  };

  filterInput = e => {
    const val = e.currentTarget.value;
    if (this.timer) {
      clearTimeout(this.timer);
      this.timer = null;
    }
    this.timer = setTimeout(this.search, 500, val);
  };

  renderSearch = () => {
    const { showSearch } = this.props;
    if (showSearch) {
      const prop = {};
      prop.onSearch = this.search;
      prop.onInput = this.filterInput;
      return <Search className={styles['events-list-search']} placeholder="事件筛选" {...prop} />;
    }
    return null;
  };

  formatSelectText = (selectedCount, allCount) => {
    const { formatText } = this.props;
    if (formatText) {
      return formatText(selectedCount, allCount);
    }
    return selectedCount === allCount ? `全选（${selectedCount}）` : `${selectedCount} 个`;
  };

  render() {
    const {
      icon,
      label = '',
      textKey = 'name',
      valueKey = 'value',
      dropdowWidth = 180,
      checkAllLabel = <b>选择全部</b>,
      boxClassName = styles['events-picker'],
      labelClassName = styles['events-label'],
      overlayClassName = styles['events-list'],
      dropdownWarpClassName = styles['events-list-warp'],
      buttonClassName = styles['event-select']
    } = this.props;
    const { checkedAll, indeterminate, selectedValues, dataSource = [] } = this.state;
    const buttonIcon = icon === true ? <Icon type="funnel-plot" /> : icon || null;
    const options = dataSource
      // .filter(item => !item.filter)
      .map(evt => ({
        label: evt[textKey],
        value: evt[valueKey],
        filter: evt.filter,
        disabled: !!evt.disabled
      }));
    return (
      <div className={boxClassName}>
        {label ? <span className={labelClassName}>{label}</span> : null}
        <Dropdown
          overlayClassName={overlayClassName}
          trigger={['click']}
          style={{ width: dropdowWidth }}
          visible={this.state.open}
          // onVisibleChange={this.visibleChange}
          overlay={
            <div className={dropdownWarpClassName} onClick={e => e.nativeEvent.stopImmediatePropagation()}>
              {this.renderSearch()}
              <Checkbox indeterminate={indeterminate} checked={checkedAll} onChange={this.checkAllChange}>
                {checkAllLabel}
              </Checkbox>
              {/* <Checkbox.Group options={options} value={selectedValues} onChange={this.checkGroupChange} /> */}
              <div className="ant-checkbox-group">
                {options.map(item => {
                  const props = {
                    disabled: item.disabled,
                    checked: selectedValues.includes(item.value),
                    style: { display: item.filter ? 'none' : '' }
                  };
                  return (
                    <Checkbox {...props} key={item.value} value={item.value} onChange={this.checkChange}>
                      {item.label}
                    </Checkbox>
                  );
                })}
              </div>
            </div>
          }
        >
          <span className={buttonClassName} onClick={this.openDropdown}>
            {buttonIcon}
            <span>{this.formatSelectText(selectedValues.length, dataSource.length)}</span>
          </span>
        </Dropdown>
      </div>
    );
  }
}
// onClick={this.openDropdown}
export default DropdownCheckList;
